﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Web.Configuration;
using FlexiCommerce.Engine;
using FlexiCommerce.Components;
using FlexiCommerce.Localization;
using FlexiCommerce.Web;

namespace FlexiCommerce
{
    public class Context
    {
        #region Initialization Methods
        /// <summary>Initializes a static instance of the N2 factory.</summary>
        /// <param name="forceRecreate">Creates a new factory instance even though the factory has been previously initialized.</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static IEngine Initialize(bool forceRecreate)
        {
            if (Singleton<IEngine>.Instance == null || forceRecreate)
            {
                Debug.WriteLine("Constructing engine " + DateTime.Now);
                Singleton<IEngine>.Instance = CreateEngineInstance();
                Debug.WriteLine("Initializing engine " + DateTime.Now);
                Singleton<IEngine>.Instance.Initialize();
            }
            return Singleton<IEngine>.Instance;
        }

        /// <summary>Sets the static factory instance to the supplied factory. Use this method to supply your own engine implementation.</summary>
        /// <param name="engine">The factory to use.</param>
        /// <remarks>Only use this method if you know what you're doing.</remarks>
        public static void Initialize(IEngine engine)
        {
            Singleton<IEngine>.Instance = engine;
        }

        private static System.Configuration.Configuration GetConfiguration()
        {
            try
            {
                return System.Web.Hosting.HostingEnvironment.IsHosted
                    ? WebConfigurationManager.OpenWebConfiguration("~")
                    : ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            }
            catch (Exception ex)
            {
                Trace.TraceWarning("Error reading configuration. This has happened when running a web site project in a virtual directory (reason unknown). " + ex);
                return null;
            }
        }

        /// <summary>Creates a factory instance and adds a http application injecting facility.</summary>
        /// <returns>A new factory.</returns>
        public static IEngine CreateEngineInstance()
        {
            try
            {
                System.Configuration.Configuration config = GetConfiguration();
                if (config == null)
                    return new FlexiCommerce.Engine.Engine(EventBroker.Instance);

                return new FlexiCommerce.Engine.Engine(config, "flexicommerce", EventBroker.Instance);
            }
            catch (SecurityException ex)
            {
                Trace.TraceInformation("Caught SecurityException, reverting to MediumTrustEngine. " + ex);
                //TODO:Install medium trust engine
                //return new MediumTrustEngine(EventBroker.Instance);
                throw;
            }
        }

        #endregion

        #region Properties: Persister, Definitions, Integrity, UrlParser, CurrentPage

        /// <summary>Gets the singleton N2 engine used to access N2 services.</summary>
        public static IEngine Current
        {
            get
            {
                if (Singleton<IEngine>.Instance == null)
                {
                    Initialize(false);
                }
                return Singleton<IEngine>.Instance;
            }
        }

        /// <summary>Gets N2 persistence manager used for database persistence of content.</summary>
        public static Persistence.IPersister Persister
        {
            get { return Current.Persister; }
        }

        /// <summary>Gets N2 persistence manager used for database persistence of content.</summary>
        public static ILocalizationManager LocalizationManager
        {
            get { return Current.LocalizationManager; }
        }

        /// <summary>Gets N2 security manager responsible of item access checks.</summary>
        public static Security.ISecurityManager SecurityManager
        {
            get { return Current.SecurityManager; }
        }

        public static IUrlParser UrlParser
        {
            get { return Current.UrlParser; }
        }
        public static Category CurrentCategory
        {
            get { return Current.UrlParser.CurrentCategory; }
        }
        #endregion
    }

}
